import com.dto.rfid.sygole.Rfid_SYGOLE_DTO;
import com.service.safe.SafeService;
import com.utils.CrcUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.ReferenceCountUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.sshd.common.io.nio2.Nio2ServiceFactory;
import org.springframework.scheduling.annotation.EnableAsync;

import java.util.ArrayList;
import java.util.List;

@EnableAsync
@Slf4j(topic = "思谷RFID业务接口类")
public class SG_RfidServiceImpl implements ISG_RfidService {

    /*返回值*/
    public static String returnStr = "";
    String ip = Rfid_SYGOLE_DTO.getIp();
    /*10001*/
    int port = Integer.parseInt(Rfid_SYGOLE_DTO.getPort());
    Bootstrap bootstrap = new Bootstrap();
    //定义客户端的NIO线程组
    EventLoopGroup group = new NioEventLoopGroup(2);

    public SG_RfidServiceImpl() {

    }

    /**
     * 读取UID
     *
     * @return
     */
    @Override
    public String readUID() {
        return null;
    }

    @Override
    public String getTagMessage() {
        return null;
    }

    @Override
    public String getSafeMessage() {
        return null;
    }

    @Override
    public String getSoftWareVesion() {
        return null;
    }

    /**
     * hex读
     *
     * @return hex字符串
     */
    @Override
    public String hexRead() {


        return null;
    }

    /**
     * hex写
     *
     * @return hex字符串（结果）
     */
    @Override
    public String hexWrite() {


        return null;
    }

    /**
     * 明文读
     *
     * @return 标签明文
     */
    @Override
    public String strRead(int len) {
        readRfid(group,len);

        return null;
    }

    /**
     * 明文写
     *
     * @return 结果状态
     */
    @Override
    public String strWrite(String info/*内容*/) {
        writeRfid(group, info);
//        FF 10 12 00 01 00 00 00 08 31 32 33 34 35 36 37 38
        return null;
    }


    private void readRfid(EventLoopGroup group,int len) {
        try {

            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    //该参数的作用就是禁止使用Nagle算法，使用于小数据即时传输
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.SO_TIMEOUT, 2000)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)

                    .option(ChannelOption.SO_REUSEADDR, true)
                    //指定化自定义客户端初始化器
                    .handler(new SG_RFID_ReadClientInitializer());
            //连接服务器


//            int len = 588;
            int startNo = 0;
            int endNo = 0;
            int n = 0;
            int more =0;
            String stringBuilder = new String();

            if(len % 120 !=0) {
                n = len / 120;
                more = len - n * 120;
//            System.out.println(n);
                for (int i = 0; i < n; i++) {
//                System.out.println(i);
                    startNo = (1 * i * 120);
                    endNo = ((i + 1) * 120 )-1;
//                    System.out.println(startNo);
//                    System.out.println(endNo);
                    String sentData = doEnCode(startNo,120);
                    stringBuilder += doConnect(sentData);


                }
                startNo = endNo+1;
                endNo = more;
//                System.out.println(startNo);
//                System.out.println(endNo);
                String sentData = doEnCode(startNo,endNo);
                stringBuilder += doConnect(sentData);

            } else {
                n = len / 120;
                for (int i = 0; i < n; i++) {
//                System.out.println(i);
                    startNo = (1 * i * 120);
                    endNo = ((i + 1) * 120 )-1;
//                    System.out.println(startNo);
//                    System.out.println(endNo);
                    String sentData = doEnCode(startNo,120);
//                    System.out.println(sentData);
                    stringBuilder += doConnect(sentData);


                }
            }
//            String r1 = a.toString() ;
           Rfid_SYGOLE_DTO.setGetRfidInfo(stringBuilder);
            System.out.println("RFIF值实际为："+Rfid_SYGOLE_DTO.getGetRfidInfo());


        } catch (Exception e) {
            e.printStackTrace();
        } finally {

           /*new SafeService();*/group.shutdownGracefully();
        }

    }

    private String doEnCode(int startNo,int endNo) {

        //需要发送的报文
        String msg1 = "FF";
        /*总长度 字段长+8*/
        String msg2 = "08";
        String msg3 = "11 00 01 00 ".replace(" ", "");

        String jinwei = "00";

        String startLen = Integer.toHexString(startNo);
        String endLen = Integer.toHexString(endNo);

        if (startLen.toUpperCase().length() < 2) {
            startLen = "0" + startLen.toUpperCase();
        } else if (startLen.toUpperCase().length() ==3){
            startLen = startLen.toUpperCase().substring(1,3);
            jinwei =  "01";
          //  System.out.println("hhaha"+startLen);
        } else {
            startLen = startLen.toUpperCase();
        }

        if (endLen.toUpperCase().length() < 2) {
            endLen = "0" + endLen.toUpperCase();
        } else {
            endLen = endLen.toUpperCase();
        }

        msg3 = msg3 +jinwei;

        String msg4 = startLen + endLen;
      //  System.out.println(msg3+msg4);

//            if (Integer.parseInt(Rfid_SYGOLE_DTO.getLen())<=120){
//                startLen = "00";
//                /*长度*/
//                msg4 = Integer.toHexString(Integer.parseInt(Rfid_SYGOLE_DTO.getLen()));
//                if (msg4.toUpperCase().length() < 2) {
//                    msg4 = "0" + msg4.toUpperCase();
//                } else {
//                    msg4 = msg4.toUpperCase();
//                }
//            }

//        msg3 = msg3+startLen;

        /*FF 08 11 00 01 00 00 00 78 41 72    0-120*/
        /*FF 08 11 00 01 00 00 78 F0 27 50     120-240*/




        /*crc*/
        String msg5 = CrcUtil.getCRC((msg1 + msg2 + msg3 + msg4)).replace(" ", "");
        String sentData = msg1 + msg2 + msg3 + msg4 + msg5;
       log.warn("发送查询指令:"+sentData);
       return sentData;
        /**/
    }

    @SneakyThrows
    private String doConnect(String sentData) {
        ChannelFuture future = bootstrap.connect(ip, port).sync();
        //16进制字符串转byte数组

        byte[] bytes = hexStrToByteArr(sentData.trim());
        ByteBuf in = Unpooled.buffer(sentData.length()+1);
        in.writeBytes(bytes);
        //发送数据给服务器
//        System.out.println(in.toString());
        future.channel().writeAndFlush(in);
        ReferenceCountUtil.release(bytes);
            //            future.channel().closeFuture().sync();
            future.sync().addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        log.error("服务端连接错误");
                    }
                }
            });
//            ChannelFuture cf = bootstrap.connect().sync(); // 异步连接服务器

           log.info("服务端连接成功..."); // 连接完成
        future.channel().closeFuture().sync(); // 异步等待关闭连接channel
        // System.out.println("连接已关闭.."); // 关闭完成
        future.syncUninterruptibly();



        return returnStr;

    }

    private void writeRfid(EventLoopGroup group, String info) {
        try {
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
                .option(ChannelOption.SO_KEEPALIVE, true)
                //该参数的作用就是禁止使用Nagle算法，使用于小数据即时传输
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
                //绑定客户端通道
                .option(ChannelOption.SO_REUSEADDR, true)
                //指定化自定义客户端初始化器
                .handler(new SG_RFID_WriteClientInitializer());

            String stringBuilder = new String();
            int len = info.length();
            int startNo = 0;
            int endNo = 0;
            int n = 0;
            int more =0;

            if(len % 120 !=0) {
                n = len / 120;
                more = len - n * 120;

//            System.out.println(n);
                for (int i = 0; i < n; i++) {
//                System.out.println(i);
                    startNo = (1 * i * 120);
                    endNo = ((i + 1) * 120 );
                    System.out.println(startNo);
                    System.out.println(endNo);
                    if (i == 0) {
//                        System.out.println(info.substring(startNo,endNo));
                        String finalString = info.substring(startNo,endNo);
                        String msg = getWriteCode(finalString,startNo,120);
                        stringBuilder += doConnect(msg);
                        System.out.println(finalString);
                    } else {
//                        System.out.println(info.substring(startNo-1,endNo));
                        String finalString = info.substring(startNo,endNo);
                        String msg = getWriteCode(finalString,startNo,120);
                        stringBuilder += doConnect(msg);
                        System.out.println(finalString);
                    }

                }

                startNo = endNo+1;
                endNo = more;
                System.out.println(startNo);
                System.out.println(endNo);
//                System.out.println(startNo);
//                System.out.println(endNo);
//                System.out.println(info.substring(startNo-1,startNo+endNo));
                String finalString = info.substring(startNo-1);
                System.out.println(finalString);
//                    String sentData = doEnCode(startNo,120);
//                    System.out.println(sentData);
                //需要发送的报文

                String msg = getWriteCode(finalString,startNo-1,endNo);
                stringBuilder += doConnect(msg);
//                stringBuilder += doConnect(info);


            } else{
                n = len / 120;
                for (int i = 0; i < n; i++) {
//                System.out.println(i);
                    startNo = (1 * i * 120);
                    endNo = ((i + 1) * 120);
                    System.out.println(startNo +":" +endNo);
                    if (startNo == 0) {
//                        System.out.println(info.substring(startNo,endNo));
                        String finalString = info.substring(startNo,endNo);
                        String msg = getWriteCode(finalString,startNo,120);
                        stringBuilder += doConnect(msg);
                        System.out.println(finalString);

                    } else {
//                        System.out.println(info.substring(startNo-1,endNo));
                        String finalString = info.substring(startNo,endNo);
                        System.out.println(finalString);
                        String msg = getWriteCode(finalString,startNo,120);
                        stringBuilder += doConnect(msg);

                    }

//                    String finalString = info.substring(startNo,120);
//                    String sentData = doEnCode(startNo,120);
//                    System.out.println(sentData);
                    //需要发送的报文
//                    String msg = getWriteCode(finalString);
//                    stringBuilder += doConnect(msg);
                }
            }



        } catch (Throwable e) {
           log.error(e.getMessage());
        } finally {
           /*new SafeService();*/group.shutdownGracefully();
        }

    }

    private String getWriteCode(String info,int start,int end) {

        /*：
         FF 80 12 00 01 00 00 78 78 75 72 3A 44 65 74 65
         63 74 2C 6C 65 78 3A 30 2E 30 2C 6C 65 7A 3A 30 2E
         30 2C 6C 65 79 3A 30 2E 30 2C 61 6C 6D 3A 30 2E 30
         2C 64 6E 6F 3A 31 2C 74 61 72 3A 30 2E 30 2C 73 69
         7A 3A 30 2E 30 2C 73 74 6E 3A 31 2C 63 6C 78 3A 30
         2E 30 2C 63 75 61 3A 30 2E 30 2C 63 6C 7A 3A 30 2E
         30 2C 65 64 70 3A 39 2C 63 6C 79 3A 30 2E 30 2C 63
         6D 61 3A 30 2E 30 2C 74 79 70 3A F8 7E */ //写120位 --  78
        String s1 = "FF";
//        String s2 = "80";
        String s2 = "";
        if (Integer.toHexString(info.length() + 8).toUpperCase().length() < 2) {
            s2 = "0" + Integer.toHexString(info.length() + 8).toUpperCase();
        } else {
            s2 = Integer.toHexString(info.length() + 8).toUpperCase();
        }
//        System.out.println(s2);
        /*FF 5B 12 00 01 00 00 00 53*/
        String jinwei  = "";
        String s3 = "12 00 01 00".replace(" ", "");
        String s4 = "";


        if (Integer.toHexString(start).toUpperCase().length() > 2) {
            s4 = Integer.toHexString(start).toUpperCase().substring(1,3);
//            System.out.println(s4);
            jinwei  = "01";
            s4 = jinwei +s4;
        } else {
            s4 = Integer.toHexString(start).toUpperCase();
            if (s4.length()<2){
                s4 = "0" +s4;
            }
            jinwei  = "00";
            s4 = jinwei +s4;
        }

        System.out.println(s4);
        /*截止位*/
        String s5 = "";
        if (Integer.toHexString(end).toUpperCase().length() < 2) {
            s5 = "0" + Integer.toHexString(end).toUpperCase();
//            System.out.println(s5);
        }else {
            s5 = Integer.toHexString(end).toUpperCase();
//            System.out.println(s5);
        }

        String head = s1 + s2 + s3 + s4 + s5;
//        System.out.println(head);
        String data = "";
        for (int i = 0; i < info.length(); i++) {
            int ch = info.charAt(i);
            String s6 = Integer.toHexString(ch);
            data = data + s6;
        }
//        System.out.println(head + data);
        String crc = CrcUtil.getCRC((head + data)).replace(" ", "");

        return head + data + crc;

    }

    /**
     * 16进制字符串转byte数组
     *
     * @param hexString
     * @return
     */
    public byte[] hexStrToByteArr(String hexString) {
        hexString = hexString.replaceAll("\\s*", "");
        if (StringUtils.isEmpty(hexString)) {
            return null;
        }
        int strLen = hexString.length();
        if ((strLen & 1) == 1) {
            //报文字符串必须是以一个字节为单位（两位为一个字节），所以当去除所有空格后的报文长度为单数时说明报文错误
            throw new RuntimeException("Incorrect message format!");
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }


    /**
     * 字符转字节
     *
     * @param c
     * @return
     */
    private byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }


}